
// 定义状态标志位
bool isCharging = false;           // 充电状态标志
bool isFullyCharged = false;       // 满电状态标志
bool isEqualizingCharge = false;   // 均衡充电状态标志
bool isBatteryInserted = false;    // 电池插入标志
bool isMainsPowerInserted = false; // 市电插入标志
bool isDataReady = false;          // 数据就绪标志
bool isDataRead = false;           // 读取就绪标志

// 定义定时器
unsigned long chongDianTime = 0; // 充电函数定时器
unsigned long equalizeTimer = 0; // 均衡充电定时器
unsigned long exitTimer = 0;     // 退出充电定时器
unsigned long startTime = 0;     // 记录开始充电时间
unsigned long ledTime = 500;     // led闪烁时间

// 宏定义时间
#define modeSwitchTimer 4000 // 模式切换时间
#define charGingTimer 2000   // 充电函数时间

// 定义状态字符串和时间信息字符串
String chargingStatus = "电池未插入";
String timeInfo = "00:00";

uint16_t crc16(const uint8_t *data, size_t length)
{ // ESP8266 CRC16计算函数
    // CRC16计算函数
    uint16_t crc = 0xFFFF;
    const uint16_t polynomial = 0xA001;
    for (size_t i = 0; i < length; i++)
    {
        crc ^= data[i];
        for (int j = 0; j < 8; j++)
        {
            if (crc & 0x0001)
            {
                crc = (crc >> 1) ^ polynomial;
            }
            else
            {
                crc >>= 1;
            }
        }
    }
    return crc;
}

void chongDian()
{
    if (millis() - chongDianTime >= charGingTimer)
    {
        if (isDataRead && isBatteryInserted)
        {
            if (isDataReady)
            {
                if (chargingStatus.indexOf("电池已断开") < 0 && chargingStatus.indexOf("充电完成") < 0)
                {
                    fasong = true;

                    if (!isCharging)
                    {
                        chargingStatus = "开始充电";
                        digitalWrite(out, HIGH);       // 打开充电器输出
                        analogWrite(U_pwm, config.Um); // 设置充电器电压
                        analogWrite(I_pwm, 0);         // 设置充电器电流
                        isCharging = true;
                        isFullyCharged = false;
                        isEqualizingCharge = false;
                        startTime = millis(); // 记录开始充电时间
                        exitTimer = millis();
                        equalizeTimer = millis();
                    }
                    // 调整判断顺序，先判断充电完成，再判断均衡充电
                    else if (U > config.mu)
                    {
                        if (millis() - exitTimer >= modeSwitchTimer)
                        {
                            // 电流低于阈值后断开输出
                            if (I < 0.1 && digitalRead(out))
                            {
                                digitalWrite(out, LOW);
                                analogWrite(U_pwm, config.Ud);
                                chargingStatus = "电池已断开";
                                preHeartTick = 0;
                            }
                            else
                            {
                                chargingStatus = "充电完成";
                                isCharging = false;
                                isFullyCharged = true;
                                preHeartTick = 0;
                                analogWrite(U_pwm, config.Ud);
                                digitalWrite(out, LOW);
                                digitalWrite(redLED, LOW);
                                digitalWrite(greenLED, HIGH);
                                exitTimer = millis();
                            }
                        }
                        equalizeTimer = millis();
                    }
                    else if (U > config.fu)
                    {
                        if (millis() - equalizeTimer >= modeSwitchTimer)
                        {
                            chargingStatus = "均衡充电";
                            analogWrite(I_pwm, config.If);
                            isEqualizingCharge = true;
                            equalizeTimer = millis();
                        }
                        exitTimer = millis();
                    }
                    else if (!isFullyCharged && !isEqualizingCharge)
                    {
                        chargingStatus = "快速充电";
                        if (millis() - startTime >= modeSwitchTimer + 2000)
                        {
                            analogWrite(I_pwm, config.I); // 设置充电器电流
                        }
                        exitTimer = millis();
                        equalizeTimer = millis();
                    }
                    if (chargingStatus.indexOf("%") < 0)
                    {
                        chargingStatus += String(Q) + "%";
                    }
                }
            }
        }
        else if (chargingStatus != "电池未插入")
        {
            isCharging = false;
            digitalWrite(out, LOW);
            digitalWrite(redLED, LOW);
            digitalWrite(greenLED, HIGH);
            analogWrite(U_pwm, config.Ud);
            chargingStatus = "电池未插入";
            fasong = true;
            preHeartTick = millis(); // 心跳计时开始，需要每隔60秒发送一次数据
        }
        chongDianTime = millis();
    }
}

void rongLiangJiSuan()
{
    if (isCharging)
    {
        Ah = (int((Wh - config.bi) / 79.00 * 100)) / 100.00;
        config.charts[int(config.shu)] = Ah;
        Q = (Ah / config.Ah) * 100;
        if (Q >= 100)
        {
            Q = 100;
        }
    }
}

void duanDianBaoCun()
{
    static bool isMainsPower = false;

    if (isDataRead && !isMainsPowerInserted != isMainsPower)
    {
        isMainsPower = !isMainsPowerInserted;
        if (!isMainsPowerInserted)
        {
            chargingStatus = "电源已断开" + String(Q) + "%再见";
            config.bi = Wh;
            sendtoTCPServer();
            if (config.Ah < Ah)
            {
                config.Ah = Ah;
            }
            if (config.shu >= charts - 1)
            {
                for (size_t i = 0; i < config.shu; i++)
                {
                    config.charts[i] = config.charts[i + 1];
                }
            }
            else
            {
                config.shu++;
            }
            saveConfig();
        }
        else
        {
            config.reboot = config.reboot + 1;
            chargingStatus = "reboot: " + String(config.reboot) + "";
            sendtoTCPServer();
            Serial.print("reboot: ");
            Serial.println(config.reboot);
            if (config.reboot >= 5)
            {
                restoreFactory();
            }
        }
        while (!digitalRead(sdin))
        {
            digitalWrite(greenLED, !digitalRead(greenLED)); // 切换红色指示灯状态
            digitalWrite(redLED, digitalRead(greenLED));    // 切换红色指示灯状态
            delay(50);
        }
    }
}

void zhiShiDeng()
{
    if (isCharging)
    {
        char h[5];
        char m[5];
        sprintf(h, "%02ld", (millis() - startTime) / 1000 / 3600);
        sprintf(m, "%02ld", ((millis() - startTime) / 1000 % 3600) / 60);
        timeInfo = String(h) + ":" + String(m);
        ledTime = map(I * 100, 50, map(config.I, 1, 200, 50, 700), 1000, 0);
        static unsigned long lastBlinkTime = 0; // 定义静态变量，记录上一次闪烁时间
        if (millis() - lastBlinkTime >= ledTime)
        {

            digitalWrite(redLED, !digitalRead(redLED)); // 切换红色指示灯状态

            if (WiFi.status() != WL_CONNECTED)
            {
                digitalWrite(greenLED, digitalRead(redLED)); // 切换红色指示灯状态
            }
            else
            {
                digitalWrite(greenLED, LOW); // 切换红色指示灯状态
            }

            lastBlinkTime = millis(); // 更新上一次闪烁时间
        }
    }
    else
    {
        digitalWrite(redLED, LOW);    // 切换红色指示灯状态
        digitalWrite(greenLED, HIGH); // 切换红色指示灯状态
    }
}

void chuanGanQI()
{
    static long IM1353B_preTick = 0;
    const int bufferSize = 37;
    uint8_t buffer[bufferSize];
    if (millis() - IM1353B_preTick >= 100)
    {
        if (Serial.available() == 0)
        {
            byte command[] = {0x01, 0x03, 0x00, 0x48, 0x00, 0x08, 0xC4, 0x1A};
            Serial.write(command, sizeof(command));
        }
        else if (Serial.available() >= bufferSize)
        {
            Serial.readBytes(buffer, bufferSize);                  // 从串口读取37个字节数据
            uint16_t calculatedCRC = crc16(buffer, 35);            // 计算前35个字节的CRC16
            uint16_t receivedCRC = (buffer[36] << 8) | buffer[35]; // 提取接收到的CRC16（最后两个字节）
            if (calculatedCRC == receivedCRC)
            {
                for (int i = 3, groupNumber = 1; groupNumber <= 4; i += 4, groupNumber++)
                {
                    uint32_t combinedValue = (buffer[i] << 24) | (buffer[i + 1] << 16) | (buffer[i + 2] << 8) | buffer[i + 3];
                    if (groupNumber == 1)
                    {
                        u = (combinedValue / 10000.0 - config.bt152_600);
                        U = u - config.equivalentResistance * I;
                    }
                    else if (groupNumber == 2)
                    {
                        I = combinedValue / 10000.0;
                    }
                    else if (groupNumber == 3)
                    {
                        P = combinedValue / 10000.0;
                    }
                    else if (groupNumber == 4)
                    {
                        Wh = combinedValue / 10;
                    }
                }
                isDataReady = true;
            }
        }
        else if (Serial.available() > 0)
        {
            while (Serial.available())
            {
                Serial.read();
            }
        }

        static int sum = 0;
        static int count = 0;
        sum += analogRead(A0);
        count++;
        static int sda = 0;
        static int sdb = 0;
        static int xdca = 0;
        static int xdcb = 0;
        if (digitalRead(sdin))
        {
            sda++;
        }
        else
        {
            sdb++;
        }
        if (digitalRead(xdcin))
        {
            xdca++;
        }
        else
        {
            xdcb++;
        }
        if (count >= 10)
        {
            float Adc = 1023 - (sum / count);
            t = map(Adc, 37, 643, 20, 60);
            analogWrite(fen, Adc - 100);
            sum = 0;
            count = 0;

            if (sda > sdb)
            {
                isMainsPowerInserted = true;
            }
            else
            {
                isMainsPowerInserted = false;
            }
            sda = 0;
            sdb = 0;
            if (xdca > xdcb)
            {
                isBatteryInserted = true;
            }
            else
            {
                isBatteryInserted = false;
            }
            xdca = 0;
            xdcb = 0;
            isDataRead = true;
        }
        IM1353B_preTick = millis();
    }
}

void chongDianQi()
{
    chongDian();
    zhiShiDeng();
    chuanGanQI();
    duanDianBaoCun();
    rongLiangJiSuan();
}